package com.moro.lisp.tools;

import java.util.ArrayList;
import java.util.List;

import com.moro.lisp.JLispData;
import com.moro.lisp.JLispFunctionName;
import com.moro.lisp.JLispType;
import com.moro.lisp.typedefine.Atom;
import com.moro.lisp.typedefine.Cons;
import com.moro.lisp.typedefine.Function;

/**
 * 鍑芥暟姹狅紝鐢ㄤ簬缁堢鎹曡幏鎵�鏈夌殑鍑芥暟鍊�
 * @author HJ
 *
 */
public class FunctionPool {
	private List<Function> pool;
	
	private Debug callStack;
	
	
	/*
	 * 榛樿鏋勯�犳柟娉�
	 */
	public FunctionPool(SymbolPool symbolPool) {
		this.callStack = new Debug();
		
		this.pool = new ArrayList<Function>();
		functionInit(symbolPool);
		this.callStack.closeDebug();

	}
	public void functionInit(SymbolPool symbolPool) {
		//鍒濆鍖栧熀鏈嚱鏁�
		this.pool.add(new Function(JLispFunctionName.CAR, symbolPool.getSymbolByString("car"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.CDR, symbolPool.getSymbolByString("cdr"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.CONS, symbolPool.getSymbolByString("cons"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.INS, symbolPool.getSymbolByString("ins"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.IF, symbolPool.getSymbolByString("if"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.ADD, symbolPool.getSymbolByString("add"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.SUB, symbolPool.getSymbolByString("sub"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.MUL, symbolPool.getSymbolByString("mul"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.DIV, symbolPool.getSymbolByString("div"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.MOD, symbolPool.getSymbolByString("mod"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.AND, symbolPool.getSymbolByString("and"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.OR, symbolPool.getSymbolByString("or"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.PROGN, symbolPool.getSymbolByString("progn"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.MORE, symbolPool.getSymbolByString("more"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.LESS, symbolPool.getSymbolByString("less"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.EQ, symbolPool.getSymbolByString("eq"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.PRINT, symbolPool.getSymbolByString("print"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.SYMBOLVALUE, symbolPool.getSymbolByString("symbolvalue"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.SYMBOLFUNCTION, symbolPool.getSymbolByString("symbolfunction"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.EVAL, symbolPool.getSymbolByString("eval"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.ATOM, symbolPool.getSymbolByString("atom"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.CONSP, symbolPool.getSymbolByString("consp"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.NUMBERP, symbolPool.getSymbolByString("numberp"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.LIST, symbolPool.getSymbolByString("list"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.GENSYM, symbolPool.getSymbolByString("gensym"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.RAND, symbolPool.getSymbolByString("rand"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.PARSELIST, symbolPool.getSymbolByString("parselist"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.NTH, symbolPool.getSymbolByString("nth"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.TIME, symbolPool.getSymbolByString("time"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.APPLY, symbolPool.getSymbolByString("apply"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.FUNCALL, symbolPool.getSymbolByString("funcall"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.LENGTH, symbolPool.getSymbolByString("length"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.MACROEXPAND, symbolPool.getSymbolByString("macroexpand"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.LOAD, symbolPool.getSymbolByString("load"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.ERROR, symbolPool.getSymbolByString("error"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.REMOVE, symbolPool.getSymbolByString("remove"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.ARGUMENTSIZE, symbolPool.getSymbolByString("argumentsize"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.SLEEP, symbolPool.getSymbolByString("sleep"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.TYPE, symbolPool.getSymbolByString("type"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.IN, symbolPool.getSymbolByString("in"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Function(JLispFunctionName.DEBUG, symbolPool.getSymbolByString("debug"),
				symbolPool.getSymbolByString("nil"), null, null));
		

	}
	
	
	
	/*
	 * 鏍规嵁鍑芥暟鍚嶅拰绗﹀彿鏌ユ壘鍑芥暟
	 */
	/*public Function getFunction(JLispFunctionName functionName, Atom atom) {
		return null;
	}*/
	
	
	
	/*
	 * 鏍规嵁鍑芥暟鍚嶏紙鏋氫妇绫诲瀷锛夌鍙峰畾涔夊嚱鏁�(娉ㄦ剰涓嶈兘瀹氫箟鍩烘湰鍑芥暟锛屽洜涓哄熀鏈嚱鏁板湪鏋勫缓鍑芥暟姹犳椂宸茶瀹氫箟锛屼絾鏄彲浠ョ敤鐩稿悓鐨勭鍙锋瘮濡俰f瀹氫箟鍏跺畠鍑芥暟)
	 */
	public Function getFunctionByFunctionName(JLispFunctionName functionName,
			Atom atom,Cons args,List<JLispData> functionBodys, List<Atom> closure) {
		if(JLispFunctionName.CUSTOMIZE != functionName) {
			return null;
		}else {
			Function function = new Function(functionName, atom, args, functionBodys, closure);
			addFunction(function);
			return function;
		}
		
	}
	public Function getFunctionByFunctionName(JLispFunctionName functionName,
			Atom atom,Atom nil,List<JLispData> functionBodys, List<Atom> closure) {
		if(JLispFunctionName.CUSTOMIZE != functionName) {
			return null;
		}else {
			Function function = new Function(functionName, atom, nil, functionBodys, closure);
			addFunction(function);
			return function;
		}
		
	}
	private void addFunction(Function function) {
		if(JLispFunctionName.CUSTOMIZE != function.functionName) {//濡傛灉涓嶆槸鑷畾涔夊嚱鏁帮紝鍒欎笉娣诲姞
			return;
		}else {
			this.pool.add(function);
		}
	}
	public void flush(SymbolPool symbolPool) {
		for(int i = 41;i < this.pool.size();i++) {
			if(!this.pool.get(i).isAlive()) {
				this.removeFunction(i--, symbolPool);;
			}
		}
	}
	private void removeFunction(int i, SymbolPool symbolPool) {
		if(null == this.pool.get(i).closure) {
			this.pool.remove(i);
			return;
		}
		for(Atom a:this.pool.get(i).closure) {
			symbolPool.findByString(a.name).symbolValues.rBind(new JLispData(this.pool.get(i), JLispType.FUNCTION));
		}
		this.pool.remove(i);
	}
	public int getFunctionPoolSize() {
		return this.pool.size();
	}
	
	public void into(JLispData[] args, JLispData functionOrMacro, JLispData caller) {
		if(JLispType.FUNCTION != functionOrMacro.type && JLispType.MACRO != functionOrMacro.type) {
			return;
		}
		
		this.callStack.into(args, functionOrMacro, caller);
		//this.curLevel += 1;
	}
	
	public void outfrom(JLispData functionOrMacro, JLispData executeAns, JLispData caller) {
		if(JLispType.FUNCTION != functionOrMacro.type && JLispType.MACRO != functionOrMacro.type) {
			return;
		}
		this.callStack.outfrom(functionOrMacro, executeAns, caller);
		//this.curLevel -= 1;
	}
	
	public void startDebug() {
		this.callStack.startDebug();
	}
	
	public void closeDebug() {
		this.callStack.closeDebug();
	}
	
	public void startDebugMode() {
		this.callStack.startDebugMode();
	}
	
	public void closeDebugMode() {
		this.callStack.closeDebugMode();
	}
	
	public boolean isLogMode() {
		return this.callStack.isLogMode();
	}
	
	public boolean isDebugMode() {
		return this.callStack.isDebugMode();
	}
}